package com.ittx.dzt.shein.util;

import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

/**
 * 希音签名工具
 * <p>
 *
 * </p>
 *
 * @author wl_code@163.com
 * @version 1.0
 * @date 2025/7/31
 */
@Slf4j
public class SheinSignUtil {

	public static String generateSheinSignature(String openKeyId, String secretKey, String path) throws Exception {

		// 步骤一：组装签名数据VALUE
		String value = openKeyId + "&" + System.currentTimeMillis() + "&" + path;
		log.debug("步骤一 - 签名数据VALUE: {}", value);

		String randomKey = RandomUtil.randomString(5);
		// 步骤二：组装签名密钥KEY
		String key = secretKey + randomKey;
		log.debug("步骤二 - 签名密钥KEY:{} ", key);

		// 步骤三：HMAC-SHA256计算并转换为十六进制
		Mac mac = Mac.getInstance("HmacSHA256");
		SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
		mac.init(secretKeySpec);
		byte[] hmacResult = mac.doFinal(value.getBytes(StandardCharsets.UTF_8));

		StringBuilder hexStringBuilder = new StringBuilder();
		for (byte b : hmacResult) {
			String hex = Integer.toHexString(0xff & b);
			if (hex.length() == 1) {
				hexStringBuilder.append('0');
			}
			hexStringBuilder.append(hex);
		}
		String hexSignature = hexStringBuilder.toString();
		log.debug("步骤三 - HMAC-SHA256结果(HEX): {}", hexSignature);

		// 步骤四：Base64编码
		String base64Signature = Base64.getEncoder().encodeToString(
				hexSignature.getBytes(StandardCharsets.UTF_8));
		log.debug("步骤四 - Base64编码结果: {}", base64Signature);

		// 步骤五：拼接RandomKey
		String finalSignature = randomKey + base64Signature;
		log.debug("步骤五 - 最终签名: {}", finalSignature);

		return finalSignature;
	}

	/**
	 * AESTools
	 *
	 * @author xu
	 * @since 2019/10/15 17:52
	 */
	@Slf4j
	public static class AESTools {

		private static final String UTF_8 = "utf-8";
		private static final String KEY_ALGORITHM = "AES";
		private static final Integer BLOCK_LENGTH = 128;
		/**
		 * 默认的加密算法
		 */
		private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
		/**
		 * 默认密钥
		 */
		private static final String DEFAULT_KEY = "space-station-default-key";
		/**
		 * 默认的IV生成seed
		 */
		private static final String DEFAULT_IV_SEED = "space-station-default-iv";

		private static final Integer IV_LENGTH = 16;


		/**
		 * 使用AES算法加密字符串
		 *
		 * @param content 待加密的字符串
		 * @return 加密后的字符串 BASE64格式
		 */
		public static String encrypt(String content) {
			return encrypt(content, DEFAULT_KEY);
		}


		/**
		 * AES 加密操作
		 *
		 * @param content 待加密内容
		 * @param key     加密密码
		 * @return 返回Base64转码后的加密数据 string
		 */
		public static String encrypt(String content, String key) {
			return encrypt(content, key, DEFAULT_IV_SEED);
		}

		/**
		 * Encrypt string.
		 *
		 * @param content the content
		 * @param key     the key
		 * @param ivSeed  the iv seed
		 * @return the string
		 */
		public static String encrypt(String content, String key, String ivSeed) {
			return encrypt(content, key, ivSeed, false);
		}

		/**
		 * AES 加密操作
		 *
		 * @param content         待加密内容
		 * @param key             加密密码
		 * @param ivSeed          the ivSeed
		 * @param useSecureRandom 是否对密钥使用随机算法
		 * @return 返回Base64转码后的加密数据 string
		 */
		public static String encrypt(String content, String key, String ivSeed, boolean useSecureRandom) {
			return encrypt(content, key, ivSeed, useSecureRandom, false);
		}


		/**
		 * AES 加密操作
		 *
		 * @param content          待加密内容
		 * @param key              加密密码
		 * @param ivSeed           the ivSeed
		 * @param useSecureRandom  是否对密钥使用随机算法
		 * @param fillIvIntoResult the fill iv into result
		 * @return 返回Base64转码后的加密数据 string
		 */
		public static String encrypt(String content, String key, String ivSeed, boolean useSecureRandom, boolean fillIvIntoResult) {
			if (content == null || content.length() == 0
					|| key == null || key.length() == 0
					|| ivSeed == null || ivSeed.length() == 0) {
				throw new IllegalArgumentException("加密内容/密钥/iv不能为空");
			}
			if (ivSeed.getBytes().length < IV_LENGTH) {
				throw new IllegalArgumentException("iv长度不能低于16 byte");
			}
			try {
				// 创建密码器
				Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

				byte[] byteContent = content.getBytes(UTF_8);
				byte[] ivSeedBytes = ivSeed.getBytes();
				//createIVBySeed(ivSeed);
				byte[] ivBytes = new byte[16];
				System.arraycopy(ivSeedBytes, 0, ivBytes, 0, 16);

				IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
				// 初始化为加密模式的密码器
				cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key, useSecureRandom), ivSpec);
				// 加密
				byte[] result = cipher.doFinal(byteContent);

				byte[] mergeResult = fillIvIntoResult ? mergeBytes(ivBytes, result) : result;
				//通过Base64转码返回
				return Base64.getEncoder().encodeToString(mergeResult);
			} catch (Exception ex) {
				log.warn("AES加密失败:{}", ex);
			}

			return null;
		}


		/**
		 * AES 解密操作
		 *
		 * @param content 待解密的字符串 BASE64格式
		 * @return 解密后的结果 string
		 */
		public static String decrypt(String content) {

			return decrypt(content, DEFAULT_KEY, DEFAULT_IV_SEED);
		}


		/**
		 * Decrypt string.
		 *
		 * @param content the content
		 * @param key     the key
		 * @return string
		 */
		public static String decrypt(String content, String key) {
			return decrypt(content, key, false);
		}

		/**
		 * Decrypt string.
		 *
		 * @param content               待解密的字符串 BASE64格式
		 * @param key                   密钥
		 * @param isIvSeedContentResult ivSeed是否在密文中
		 * @return 解密后的结果 string
		 */
		public static String decrypt(String content, String key, boolean isIvSeedContentResult) {
			if (content == null || content.length() == 0 || key == null || key.length() == 0) {
				throw new IllegalArgumentException("密文和密钥不能为空");
			}
			if (!isIvSeedContentResult) {
				return decrypt(content, key, DEFAULT_IV_SEED);
			}
			int ivLength = IV_LENGTH;

			byte[] decode = Base64.getDecoder().decode(content);
			if (decode.length <= ivLength) {
				// 没有iv信息
				throw new IllegalArgumentException("错误的密文");
			}
			byte[] ivBytes = new byte[ivLength];
			byte[] realData = new byte[decode.length - ivLength];

			System.arraycopy(decode, 0, ivBytes, 0, ivLength);
			System.arraycopy(decode, ivLength, realData, 0, decode.length - ivLength);
			return decrypt(Base64.getEncoder().encodeToString(realData), key, ivBytes);
		}

		/**
		 * AES 解密操作
		 *
		 * @param content 待解密的字符串 BASE64格式
		 * @param key     密钥
		 * @param iv      the iv
		 * @return 解密后的结果 string
		 */
		public static String decrypt(String content, String key, byte[] iv) {
			return decrypt(content, key, iv, false);
		}

		/**
		 * Decrypt string.
		 *
		 * @param content the content
		 * @param key     the key
		 * @param iv      the iv
		 * @return the string
		 */
		public static String decrypt(String content, String key, String iv) {
			if (iv == null || iv.getBytes().length < IV_LENGTH) {
				throw new IllegalArgumentException("iv长度不能低于16 byte");
			}
			byte[] ivSeedBytes = iv.getBytes();
			byte[] ivBytes = new byte[16];
			System.arraycopy(ivSeedBytes, 0, ivBytes, 0, 16);

			return decrypt(content, key, ivBytes, false);
		}


		/**
		 * AES 解密操作
		 *
		 * @param content         待解密的字符串 BASE64格式
		 * @param key             密钥
		 * @param iv              the iv
		 * @param useSecureRandom 是否对密钥使用随机算法
		 * @return 解密后的结果 string
		 */
		public static String decrypt(String content, String key, byte[] iv, boolean useSecureRandom) {
			if (content == null || content.length() == 0 || key == null || key.length() == 0) {
				throw new IllegalArgumentException("密文和密钥不能为空");
			}
			try {
				//实例化
				Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
				IvParameterSpec ivSpec = new IvParameterSpec(iv);
				//使用密钥初始化，设置为解密模式
				cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key, useSecureRandom), ivSpec);
				//执行操作
				byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));
				log.info("解密完成");
				return new String(result, "utf-8");
			} catch (Exception ex) {
				log.warn("AES解密失败:{}", ex);
			}

			return null;
		}

		/**
		 * 生成加密秘钥
		 *
		 * @return
		 */
		private static SecretKeySpec getSecretKey(final String key, boolean randomKey) {
			try {
				if (randomKey) {
					//返回生成指定算法密钥生成器的 KeyGenerator 对象
					KeyGenerator kg = null;
					kg = KeyGenerator.getInstance(KEY_ALGORITHM);
					SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
					secureRandom.setSeed(key.getBytes());
					//AES 要求密钥长度为 128
					kg.init(BLOCK_LENGTH, secureRandom);
					//生成一个密钥
					SecretKey secretKey = kg.generateKey();
					// 转换为AES专用密钥
					return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
				} else {
					// 转换为AES专用密钥
					return new SecretKeySpec(Arrays.copyOf(key.getBytes(UTF_8), 16), KEY_ALGORITHM);
				}
			} catch (Exception ex) {
				log.warn("AES生成加密秘钥失败:{}", ex);
				throw new RuntimeException("AES生成加密秘钥失败", ex);
			}
		}


		/**
		 * 生成16位iv偏移量
		 *
		 * @param seed
		 * @return
		 */
		private static byte[] createIVBySeed(String seed) {
			try {
				SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
				secureRandom.setSeed(seed.getBytes());
				byte[] iv = new byte[16];
				secureRandom.nextBytes(iv);
				return iv;
			} catch (Exception ex) {
				log.warn("AES生成加密秘钥失败:{}", ex);
				throw new RuntimeException("AES生成加密秘钥失败", ex);
			}
		}

		/**
		 * @param data1
		 * @param data2
		 * @return data1 与 data2拼接的结果
		 */
		private static byte[] mergeBytes(byte[] data1, byte[] data2) {
			byte[] data3 = new byte[data1.length + data2.length];
			System.arraycopy(data1, 0, data3, 0, data1.length);
			System.arraycopy(data2, 0, data3, data1.length, data2.length);
			return data3;

		}


	}
}
